﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Security;
using System.ServiceModel.Channels;
using Microsoft.Cryptography.WCF;

namespace Microsoft.Cryptography.Samples.WCF
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                WcfService01.SayHelloWorldServiceClient client = new WcfService01.SayHelloWorldServiceClient();

                Binding binding = client.Endpoint.Binding;

                // redefining the SecurityAlgorithmSuite
                // This change is necessary, because The WCF-framework
                // rises exceptions, if a SecurityAlgorithmSuite with RSA-SHA256 ist used in an 
                // Asymmetric scenario. These exceptions are only raised, if the type of the used 
                // SecurityAlgorithmSuite is one of the out-of-thebox SecurityAlgorithmSuites, which
                // are using RSA-SHA256. (see comments in Microsoft.Cryptography.WCF.SecurityAlgorithmSuiteWrapper
                // for a more detailed explanation.
                if (binding is WSHttpBinding)
                {
                    MessageSecurityOverHttp messageSecurity = (MessageSecurityOverHttp)((WSHttpBinding)binding).Security.Message;
                    SecurityAlgorithmSuite sas = messageSecurity.AlgorithmSuite;
                    messageSecurity.AlgorithmSuite = new SecurityAlgorithmSuiteWrapper(sas);
                }
                else if (binding is System.ServiceModel.BasicHttpBinding)
                {
                    BasicHttpMessageSecurity basicSecurity = (BasicHttpMessageSecurity)((BasicHttpBinding)binding).Security.Message;
                    SecurityAlgorithmSuite sas = basicSecurity.AlgorithmSuite;
                    basicSecurity.AlgorithmSuite = new SecurityAlgorithmSuiteWrapper(sas);
                }
                else
                {
                    throw new Exception("This client only supports the bindings 'System.ServiceModel.WSHttpBinding' and 'System.ServiceModel.BasicHttpBinding'.");
                }

                
                // Remove the ClientCredentials behavior.
                System.ServiceModel.Description.ClientCredentials clientCredentials = null;
                
                foreach (System.ServiceModel.Description.IEndpointBehavior behavior in client.ChannelFactory.Endpoint.Behaviors)
                {
                    if (behavior is System.ServiceModel.Description.ClientCredentials)
                    {
                        clientCredentials = (System.ServiceModel.Description.ClientCredentials)behavior;
                    }
                }

                if (clientCredentials == null)
                {
                    clientCredentials = new System.ServiceModel.Description.ClientCredentials();
                }

                Console.WriteLine("Client Certificate (Thumbprint): {0}", clientCredentials.ClientCertificate.Certificate.Thumbprint);
                Console.WriteLine("Client Certificate (PublicKey): {0}", clientCredentials.ClientCertificate.Certificate.GetPublicKeyString());
                Console.WriteLine("Client Certificate (HasPrivateKey): {0}", clientCredentials.ClientCertificate.Certificate.HasPrivateKey);
                Console.WriteLine("Client Certificate (PrivateKey): {0}", clientCredentials.ClientCertificate.Certificate.PrivateKey != null ? clientCredentials.ClientCertificate.Certificate.PrivateKey.ToXmlString(true) : "<NULL>");

                client.ChannelFactory.Endpoint.Behaviors.Remove<System.ServiceModel.Description.ClientCredentials>();

                // Add a custom client credentials instance to the behaviors collection.
                client.ChannelFactory.Endpoint.Behaviors.Add(new ClientCredentials(clientCredentials));
                
                // Call the sample WCFService
                Console.WriteLine(client.SayHelloWorld());
            }
            catch (Exception error)
            {
                Console.WriteLine(error);
            }

            Console.WriteLine();
            Console.WriteLine("Press any key to quit program...");
            Console.ReadKey();
        }
    }
}
